﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using AzukiMap.Layer;
using System.Collections.Generic;
using AzukiMap.Renderer;
using AzukiMap.MapSource;

namespace AzukiMapUI
{
	public partial class ExpressionSelect : UserControl
	{
        DialogOpener _dialogOpener;
        IVectorStyle _style;
        bool _inited = false;
        const double GRID_HEIGHT = 26;

        public MapSourceTypes LayerType
        {
            set { 
                SetRowVisibility(value); 
            }
        }

        public IVectorStyle Style
        {
            get { return _style; }
            set { 
                _style = value;
                SetForm();
            }
        }

		public ExpressionSelect()
		{
			// Required to initialize variables
			InitializeComponent();
            _dialogOpener = new DialogOpener();
            _inited = true;

            MinimizeAllRows();
		}

        void SetForm()
        {
            TbPointWidth.Text = _style.PointWidth.ToString();
            TbPointHeight.Text = _style.PointHeight.ToString();
            TbPointCenterX.Text = _style.AdjustX.ToString();
            TbPointCenterY.Text = _style.AdjustY.ToString();
            TbFillOpacity.Text = (_style.Opacity * 100).ToString();
            TbStrokeOpacity.Text = (_style.Stroke.Opacity * 100).ToString();
            TbStrokeWidth.Text = _style.StrokeThickness.ToString();
            CbStrokeEndStyle.SelectedIndex = (int)_style.StrokeEndLineCap;
            CbStrokeJoinStyle.SelectedIndex = (int)_style.StrokeLineJoin;
            RtFillColor.Fill = _style.Fill;
            RtStrokeColor.Fill = _style.Stroke;
        }

        void SetRowVisibility(MapSourceTypes layerType)
        {
            MinimizeAllRows();

            if (layerType == MapSourceTypes.Point ||
                layerType == MapSourceTypes.MultiPoint)
            {
                RowPointStyle.Height = new GridLength(GRID_HEIGHT);
                RowPointWidth.Height = new GridLength(GRID_HEIGHT);
                RowPointHeight.Height = new GridLength(GRID_HEIGHT);
                RowPointCenter.Height = new GridLength(GRID_HEIGHT);
                RowFillColor.Height = new GridLength(GRID_HEIGHT);
                RowFillOpacity.Height = new GridLength(GRID_HEIGHT);
                RowStrokeColor.Height = new GridLength(GRID_HEIGHT);
                RowStrokeWidth.Height = new GridLength(GRID_HEIGHT);
                RowStrokeOpacity.Height = new GridLength(GRID_HEIGHT);
                RowStrokeStyle.Height = new GridLength(GRID_HEIGHT);
                RowEndStyle.Height = new GridLength(GRID_HEIGHT);
            }
            if (layerType == MapSourceTypes.LineString ||
                layerType == MapSourceTypes.MultiLineString)
            {
                RowStrokeColor.Height = new GridLength(GRID_HEIGHT);
                RowStrokeWidth.Height = new GridLength(GRID_HEIGHT);
                RowStrokeOpacity.Height = new GridLength(GRID_HEIGHT);
                RowStrokeStyle.Height = new GridLength(GRID_HEIGHT);
                RowEndStyle.Height = new GridLength(GRID_HEIGHT);
                RowJoinStyle.Height = new GridLength(GRID_HEIGHT);
            }
            if (layerType == MapSourceTypes.Polygon ||
                layerType == MapSourceTypes.MultiPolygon)
            {
                RowFillColor.Height = new GridLength(GRID_HEIGHT);
                RowFillOpacity.Height = new GridLength(GRID_HEIGHT);
                RowStrokeColor.Height = new GridLength(GRID_HEIGHT);
                RowStrokeWidth.Height = new GridLength(GRID_HEIGHT);
                RowStrokeOpacity.Height = new GridLength(GRID_HEIGHT);
                RowStrokeStyle.Height = new GridLength(GRID_HEIGHT);
                RowEndStyle.Height = new GridLength(GRID_HEIGHT);
                RowJoinStyle.Height = new GridLength(GRID_HEIGHT);
            }

        }

        void MinimizeAllRows()
        {
            RowPointStyle.Height = new GridLength(0);
            RowPointWidth.Height = new GridLength(0);
            RowPointHeight.Height = new GridLength(0);
            RowPointCenter.Height = new GridLength(0);
            RowFillColor.Height = new GridLength(0);
            RowFillOpacity.Height = new GridLength(0);
            RowStrokeColor.Height = new GridLength(0);
            RowStrokeWidth.Height = new GridLength(0);
            RowStrokeOpacity.Height = new GridLength(0);
            RowStrokeStyle.Height = new GridLength(0);
            RowEndStyle.Height = new GridLength(0);
            RowJoinStyle.Height = new GridLength(0);
        }

        Brush GetStrokeBrush()
        {
            return RtStrokeColor.Fill;
        }

        Brush GetFillBrush()
        {
            return RtFillColor.Fill;
        }

        private void BtnPointStyle_Click(object sender, RoutedEventArgs e)
        {
            IconSelector iconSelector = new IconSelector();
            _dialogOpener.OpenDialog(iconSelector);
        }

        void SetPointWidth()
        {
            string inputStr = TbPointWidth.Text;
            if ( FormInputControl.CheckPositiveDouble(
                inputStr, IconErrorPointWidth)) {
                    _style.PointWidth = double.Parse(inputStr);
            }
        }

        void SetPointHeight()
        {
            string inputStr = TbPointHeight.Text;
            if ( FormInputControl.CheckPositiveDouble(
                inputStr, IconErrorPointHeight)) {
                    _style.PointHeight = double.Parse(inputStr);
            }
        }

        void SetPointCenterX()
        {
            string inputStr = TbPointCenterX.Text;
            if (FormInputControl.CheckPositiveDouble(inputStr, IconErrorPointCenter))
            {
                _style.AdjustX = double.Parse(inputStr);
            }
        }

        void SetPointCenterY()
        {
            string inputStr = TbPointCenterY.Text;
            if (FormInputControl.CheckPositiveDouble(inputStr, IconErrorPointCenter))
            {
                _style.AdjustY = double.Parse(inputStr);
            }
        }

        void SetFillOpacity()
        {
            string inputStr = TbFillOpacity.Text;
            if (FormInputControl.CheckNumberBetween(inputStr, IconErrorFillOpacity, 0,100))
            {
                _style.Fill.Opacity = double.Parse(inputStr) / 100;
            }
        }

        void SetStrokeWidth()
        {
            string inputStr = TbStrokeWidth.Text;
            if (FormInputControl.CheckPositiveDouble(inputStr, IconErrorStrokeWidth, true ))
            {
                _style.StrokeThickness = double.Parse(inputStr);
            }
        }

        void SetStrokeOpacity()
        {
            string inputStr = TbStrokeOpacity.Text;
            if (FormInputControl.CheckNumberBetween(inputStr, IconErrorStrokeOpacity,0,100))
            {
                _style.Stroke.Opacity = double.Parse(inputStr) / 100;
            }

        }

        void SetStrokeEndStyle()
        {
            int selectedIndex = CbStrokeEndStyle.SelectedIndex;
            PenLineCap lineCap = GetLineCapFromId(selectedIndex);
            _style.StrokeStartLineCap = lineCap;
            _style.StrokeEndLineCap = lineCap;
            _style.StrokeDashCap = lineCap;
        }

        void SetStrokeLineJoin()
        {
            int selectedIndex = CbStrokeJoinStyle.SelectedIndex;
            PenLineJoin lineJoin = GetLineJoinFromId(selectedIndex);
            _style.StrokeLineJoin = lineJoin;
        }

        private void TbPointWidth_LostFocus(object sender, RoutedEventArgs e)
        {
            if (!_inited)
            {
                return;
            }
            SetPointWidth();
        }

        private void TbPointHeight_LostFocus(object sender, RoutedEventArgs e)
        {
            if (!_inited)
            {
                return;
            }
            SetPointHeight();
        }

        private void TbPointCenterX_LostFocus(object sender, RoutedEventArgs e)
        {
            if (!_inited)
            {
                return;
            }
            SetPointCenterX();
        }

        private void TbPointCenterY_LostFocus(object sender, RoutedEventArgs e)
        {
            if (!_inited)
            {
                return;
            }
            SetPointCenterY();
        }

        private void TbFillOpacity_LostFocus(object sender, RoutedEventArgs e)
        {
            if (!_inited)
            {
                return;
            }
            SetFillOpacity();
        }

        private void TbStrokeWidth_LostFocus(object sender, RoutedEventArgs e)
        {
            if (!_inited)
            {
                return;
            }
            SetStrokeWidth();
        }

        private void TbStrokeOpacity_LostFocus(object sender, RoutedEventArgs e)
        {
            if (!_inited)
            {
                return;
            }
            SetStrokeOpacity();
        }

        private void CbStrokeStyle_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (!_inited)
            {
                return;
            }

        }

        private void CbStrokeEndStyle_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (!_inited)
            {
                return;
            }
            SetStrokeEndStyle();
        }

        private void CbStrokeJoinStyle_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (!_inited)
            {
                return;
            }

        }

        private void BtnStrokeColor_Click(object sender, RoutedEventArgs e)
        {
            ColorDialog colorDialog = new ColorDialog();
            _dialogOpener.OpenDialog(colorDialog);
        }

        private void BtnFillColor_Click(object sender, RoutedEventArgs e)
        {

        }

        PenLineCap GetLineCapFromId(int id)
        {
            switch (id)
            {
                case (int)PenLineCap.Flat:
                    return PenLineCap.Flat;
                case (int)PenLineCap.Round:
                    return PenLineCap.Round;
                case (int)PenLineCap.Square:
                    return PenLineCap.Square;
                case (int)PenLineCap.Triangle:
                    return PenLineCap.Triangle;
                default:
                    return PenLineCap.Flat;
            }
        }

        PenLineJoin GetLineJoinFromId(int id)
        {
            switch (id)
            {
                case (int)PenLineJoin.Bevel:
                    return PenLineJoin.Bevel;
                case (int)PenLineJoin.Miter:
                    return PenLineJoin.Miter;
                case (int)PenLineJoin.Round:
                    return PenLineJoin.Round;
                default:
                    return PenLineJoin.Round;
            }
        }
	}
}